﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.IO;
using System.Net.Sockets;

using Isis;

namespace ConsoleApplication1
{
    [QS.Fx.Reflection.ComponentClass("1`1", "Custom Graph", "A simple plain graph with a graphical user interface.")]
    public partial class Chart : QS.Fx.Component.Classes.UI, QS.Fx.Interface.Classes.ICheckpointedCommunicationChannelClient<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>
    {
        private Random random = new Random();
        private int pointIndex = 0;

        int UPDATE = 1;
        delegate void stringArg(string who, string val);
        bool open_file = false;

        StreamReader file;
        Group myGroup;

        public Chart(QS.Fx.Object.IContext _mycontext,
            [QS.Fx.Reflection.Parameter("channel", QS.Fx.Reflection.ParameterClass.Value)] 
            QS.Fx.Object.IReference<QS.Fx.Object.Classes.ICheckpointedCommunicationChannel<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>>
                _channel)
            : base(_mycontext)
        {
            //System.Windows.Forms.MessageBox.Show("From text constructor!");
            InitializeComponent();
            
            this._channelendpoint = _mycontext.DualInterface<
                QS.Fx.Interface.Classes.ICheckpointedCommunicationChannel<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>,
                QS.Fx.Interface.Classes.ICheckpointedCommunicationChannelClient<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>>(this);

            if (_channel != null)
            {
                QS.Fx.Object.Classes.ICheckpointedCommunicationChannel<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText> _channelproxy =
                    _channel.Dereference(_mycontext);

                QS.Fx.Endpoint.Classes.IDualInterface<
                    QS.Fx.Interface.Classes.ICheckpointedCommunicationChannelClient<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>,
                        QS.Fx.Interface.Classes.ICheckpointedCommunicationChannel<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>>
                            _otherendpoint =
                                _channelproxy.Channel;

                this._channelconnection = ((QS.Fx.Endpoint.Classes.IEndpoint)this._channelendpoint).Connect(_otherendpoint);
            }
            
            /***** Isis-2 *****/
            IsisSystem.Start();
            myGroup = Isis.Group.Lookup("LDO");
            if (myGroup == null)
                myGroup = new Group("LDO");
            myGroup.Handlers[UPDATE] += (stringArg)delegate(string name, string val)
            {
                lock (this)
                {
                    string _new_text = val;
                    //System.Windows.Forms.MessageBox.Show("Received: " + _new_text);
                    if (!_new_text.Equals(this._text))
                    {
                        this._text = _new_text;
                        _Refresh();
                        open_file = true;
                    }

                }
            };
            
            myGroup.Join();

            client = new TcpClient("10.32.233.35", 9090);
            s = client.GetStream();
            sr = new StreamReader(s);

            //MessageBox.Show(IsisSystem.GetMyAddress().ToStringVerboseFormat());
            /*************/
        }
        TcpClient client;
        Stream s;
        StreamReader sr;

        private void timerRealTimeData_Tick(object sender, System.EventArgs e)
        {
            // Define some variables
            int numberOfPointsInChart = 0;
            int numberOfPointsAfterRemoval = 0;
            String line;
            String[] parts;
            String[] pparts;

            // Simulate adding new data points
            //int numberOfPointsAddedMax = 5;
            int x;
            double y;

            line = sr.ReadLine();

            parts = line.Split(',');
            double minY = double.MaxValue;
            double maxY = double.MinValue;
            foreach (String point in parts)
            {
                pparts = point.Split(' ');
                x = Convert.ToInt32(pparts[0]);
                y = Convert.ToDouble(pparts[1]);

                //System.Windows.Forms.MessageBox.Show(y + "");

                if (y > maxY)
                    maxY = y;
                if (y < minY) 
                    minY = y;
                //chart1.Series[0].Points.AddXY(x,y);
                DataPoint point1 = new DataPoint();
                point1.SetValueXY(x, y);

                //point1.ToolTip = string.Format("{0}, {1}", x, y);
                //point1.Label = y + "";
                chart1.Series[0].Points.Add(point1);
                pointIndex = x + 1;
            }
            numberOfPointsInChart = 500;// parts.Length;//chart1.Series[0].Points.Count;
            numberOfPointsAfterRemoval = parts.Length;
            /*for (int pointNumber = 0; pointNumber < numberOfPointsAddedMax; pointNumber++)
            {                
                line = file.ReadLine();
                parts = line.Split(' ');
                chart1.Series[0].Points.AddXY(pointIndex + 1, Convert.ToInt32(parts[1]));
                _text += (pointIndex + 1) + " " + Convert.ToInt32(parts[1]) + "\n";
                ++pointIndex;
            }*/       

            // Adjust Y & X axis scale
            chart1.ResetAutoValues();            

            // Keep a constant number of points by removing them from the left
            while (chart1.Series[0].Points.Count > numberOfPointsInChart)
            {
                // Remove data points on the left side
                while (chart1.Series[0].Points.Count > numberOfPointsAfterRemoval)
                {
                    chart1.Series[0].Points.RemoveAt(0);
                }

                // Adjust X axis scale
                chart1.ChartAreas["Default"].AxisX.Minimum = pointIndex - numberOfPointsAfterRemoval;
                chart1.ChartAreas["Default"].AxisX.Maximum = chart1.ChartAreas["Default"].AxisX.Minimum + numberOfPointsInChart;                
            }
            //chart1.ChartAreas["Default"].AxisY.Minimum = minY;
            //chart1.ChartAreas["Default"].AxisY.Maximum = maxY;

            // Invalidate chart
            chart1.Invalidate();
        }

        [QS.Fx.Base.Inspectable("channelendpoint")]
        private QS.Fx.Endpoint.Internal.IDualInterface<
            QS.Fx.Interface.Classes.ICheckpointedCommunicationChannel<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>,
            QS.Fx.Interface.Classes.ICheckpointedCommunicationChannelClient<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>>
                _channelendpoint;

        [QS.Fx.Base.Inspectable("channelconnection")]
        private QS.Fx.Endpoint.IConnection _channelconnection;

        private string _text = string.Empty;
        private bool _editing;
        private DateTime _lastchanged;
        private System.Threading.Timer _timer, _dragtimer;

        private const int EditingTimeoutInMilliseconds1 = 1000;
        private const int EditingTimeoutInMilliseconds2 = 100;

        void QS.Fx.Interface.Classes.ICheckpointedCommunicationChannelClient<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>.Initialize(
            QS.Fx.Value.Classes.IText _checkpoint)
        {
            lock (this)
            {
                string _new_text = (_checkpoint != null) ? _checkpoint.Text : null;
                if (_new_text == null)
                {
                    _new_text = string.Empty;
                }
                if (!_new_text.Equals(this._text))
                {
                    this._text = _new_text;
                    _Refresh();
                }
            }
        }

        void QS.Fx.Interface.Classes.ICheckpointedCommunicationChannelClient<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>.Receive(
            QS.Fx.Value.Classes.IText _message)
        {
            /*lock (this)
            {
                string _new_text = _message.Text;
                System.Windows.Forms.MessageBox.Show("Received: " + _new_text);
                if (!_new_text.Equals(this._text))
                {
                    this._text = _new_text;
                    _Refresh();
                }
            }*/
        }

        QS.Fx.Value.Classes.IText
            QS.Fx.Interface.Classes.ICheckpointedCommunicationChannelClient<QS.Fx.Value.Classes.IText, QS.Fx.Value.Classes.IText>.Checkpoint()
        {
            return new QS.Fx.Value.UnicodeText(this._text);
        }

        private void _Refresh()
        {
            lock (this)
            {
                //System.Windows.Forms.MessageBox.Show("Refresh");
                if (!_editing)
                {
                    if (InvokeRequired)
                        BeginInvoke(new QS.Fx.Base.Callback(this._Refresh));
                    else
                    {
                        //put code to receive value here
                    }
                }
            }
        }

    }
}
